<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Zones Profiling</title>
    <link rel="stylesheet" href="css/style.css" />
    <script>
      __Zone_disable_Error = true;
      __Zone_disable_on_property = true;
      __Zone_disable_geolocation = true;
      __Zone_disable_toString = true;
      __Zone_disable_blocking = true;
      __Zone_disable_PromiseRejectionEvent = true;
    </script>
    <script src="../dist/zone.js"></script>
    <script src="../dist/long-stack-trace-zone.js"></script>
  </head>
  <body>
    <h1>Profiling with Zones</h1>

    <button id="b1">Start Profiling</button>

    <script>
      /*
       * Let's say we want to know the CPU cost from some action
       * that includes async tasks. We can do this with zones!
       */

      /*
       * For this demo, we're going to sort an array using an async
       * algorithm when a button is pressed.
       */
      function sortAndPrintArray (unsortedArray) {
        profilingZoneSpec.reset();
        asyncBogosort(unsortedArray, function (sortedArray) {
          console.log(sortedArray);
          console.log('sorting took ' + profilingZoneSpec.time() + ' of CPU time');
        });
      }


      /*
       * This is a really efficient algorithm.
       *
       * First, check if the array is sorted.
       * - If it is, call the wrapCallback
       * - If it isn't, randomize the array and recur
       *
       * This implementation is async because JavaScript
       */
      function asyncBogosort (arr, cb) {
        setTimeout(function () {
          if (isSorted(arr)) {
            cb(arr);
          } else {
            var newArr = arr.slice(0);
            newArr.sort(function () {
              return Math.random() - 0.5;
            });
            asyncBogosort(newArr, cb);
          }
        }, 0);
      }

      function isSorted (things) {
        for (var i = 1; i < things.length; i += 1) {
          if (things[i] < things[i - 1]) {
            return false;
          }
        }
        return true;
      }


      /*
       * Bind button
       */
      function main () {
        var unsortedArray = [3,4,1,2,7];
        b1.addEventListener('click', function () {
          sortAndPrintArray(unsortedArray);
        });
      }


      /*
       * This zone starts a timer at the start of each taskEnv,
       * and stops it at the end. It accumulates the total run
       * time internally, exposing it via `zone.time()`
       *
       * Note that this is the time the CPU is spending doing
       * bogosort, as opposed to the time from the start
       * of the algorithm until it's completion.
       */
      var profilingZoneSpec = (function () {
        var time = 0,
            // use the high-res timer if available
            timer = performance ?
                        performance.now.bind(performance) :
                        Date.now.bind(Date);
        return {
          onInvokeTask: function (delegate, current, target, task, applyThis, applyArgs) {
            this.start = timer();
            delegate.invokeTask(target, task, applyThis, applyArgs);
            time += timer() - this.start;
          },
          time: function () {
            return Math.floor(time*100) / 100 + 'ms';
          },
          reset: function () {
            time = 0;
          }
        };
      }());


      /*
       * Bootstrap the app
       */
      Zone.current.fork(profilingZoneSpec).run(main);
    </script>
  </body>
</html>
